import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

public class Patch {

    public static void main(String[] args) throws IOException, GitAPIException {
        String gitDir = args[0];
        String oldVersion = args[1];
        String nowVersion = args[2];
        String patchDir = args[3];
        String sourceDir = args[4];
        FileUtil.del(Paths.get(patchDir, DateUtil.today()));
        List<String> fileList = filePath(gitDir, oldVersion, nowVersion);
        patch(fileList, sourceDir, gitDir, patchDir);
    }

    private static void patch(List<String> fileList, String sourceDir, String gitDir, String patchDir) {
        fileList.forEach(p -> {
            if (p.contains("main/java")) {
                p = StrUtil.removePrefix(p, "src/main/java");
            }
            if (p.contains(".java")) {
                p = StrUtil.replace(p, ".java", ".class");
            }
            if (p.contains("main/resources")) {
                p = StrUtil.removePrefix(p, "src/main/resources");
            }
            if (sourceDir != null) {
                String[] sourceDirList = sourceDir.split(",");
                for (String source : sourceDirList) {
                    if (p.contains(source)) {
                        p = StrUtil.removePrefix(p, source);
                    }
                }
            }

            Path source = Paths.get(gitDir, "target/classes", p);
            Path target = Paths.get(patchDir, DateUtil.today(), "WEB-INF/classes/", p).getParent();
            File file = target.toFile();
            //不是文件夹，创建文件夹
            if (!file.isDirectory()) {
                file.mkdirs();
            }
            //拷贝文件
            FileUtil.copy(source.toFile(), file, true);
        });
        ZipUtil.zip(Paths.get(patchDir, DateUtil.today()).toFile());
    }

    public static List<String> filePath(String gitDir, String oldVersion, String nowVersion) throws IOException, GitAPIException {
        //获取仓库
        Repository repo = FileRepositoryBuilder.create(Paths.get(gitDir, ".git").toFile());
        Git git = new Git(repo);
        CanonicalTreeParser old = new CanonicalTreeParser();
        CanonicalTreeParser now = new CanonicalTreeParser();
        ObjectReader reader = repo.newObjectReader();
        RevWalk revWalk = new RevWalk(repo);
        RevTree revTree = revWalk.parseTree(repo.resolve(oldVersion));
        old.reset(reader, revTree.getId());
        RevTree nowTree = revWalk.parseTree(repo.resolve(nowVersion));
        now.reset(reader, nowTree.getId());
        List<DiffEntry> diffEntryList = git.diff()
                .setOldTree(old)
                .setNewTree(now)
                .setShowNameAndStatusOnly(true)
                .call();
        return diffEntryList
                .stream()
                .map(DiffEntry::getNewPath)
                .collect(Collectors.toList());
    }
}
